package com.nuoniu.sibanyun.controllerAdvice;

import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.common.result.HttpResult;
import com.nuoniu.sibanyun.common.result.ResultStatusCode;
import lombok.extern.log4j.Log4j2;
import org.apache.ibatis.exceptions.IbatisException;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.NonTransientDataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.*;

import javax.validation.ConstraintViolationException;

@RestControllerAdvice
@Log4j2
public class DefaultExceptionHandler {


    /**
     * 400 - Bad Request
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({HttpMessageNotReadableException.class, MissingServletRequestParameterException.class, BindException.class,
            ServletRequestBindingException.class, MethodArgumentNotValidException.class, ConstraintViolationException.class})
    public HttpResult handleHttpMessageNotReadableException(Exception e) {
        log.info("参数解析失败", e);
        if (e instanceof BindException){
            return HttpResult.error(ResultStatusCode.BAD_REQUEST.getCode(), "参数解析失败");
        }
        return HttpResult.error(ResultStatusCode.BAD_REQUEST.getCode(), "参数解析失败");
    }

    /**
     * 405 - Method Not Allowed
     * 带有@ResponseStatus注解的异常类会被ResponseStatusExceptionResolver 解析
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public HttpResult handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.error("不支持当前请求方法", e);
        return HttpResult.error(ResultStatusCode.METHOD_NOT_ALLOWED.getCode(), null);
    }


    /**
     * 自定义 业务异常
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(NuoNiuException.class)
    public HttpResult handleNuoNiuException(NuoNiuException e) {
        return HttpResult.error(e.getCode(), e.getMsg());
    }


    /**
     * 其他全局异常在此捕获
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Throwable.class)
    public HttpResult handleException(Throwable e) {
        String message = e.getMessage();
        if(StringUtils.isBlank(message)){
            message = e.getLocalizedMessage();
        }
        if(StringUtils.isBlank(message) && null != e.getCause()){
            message = e.getCause().getMessage();
        }
        if(StringUtils.isBlank(message)  && null != e.getCause()){
            message = e.getCause().getLocalizedMessage();
        }
        log.error("服务运行异常：", e);
//        log.error("服务运行异常__{}:{}", e.getClass().getName() ,message);
        //身份验证 错误信息（如果没有进入controller,就无法捕获该异常）
        if(e instanceof AuthenticationException){
            return HttpResult.error("身份认证错误:"+e.getMessage());
        }
        //权限验证 错误信息
        if(e instanceof AccessDeniedException){
            return HttpResult.error(ResultStatusCode.REQUEST_FORBIDDEN);
        }
        //拦截SQL 错误提示
//        if(e instanceof DataAccessException){
//            Throwable rootCause = ((NonTransientDataAccessException) e).getRootCause();
//            if(null != rootCause  && rootCause instanceof NuoNiuException){
//                return HttpResult.error(((NuoNiuException) rootCause).getMsg());
//            }
//            return HttpResult.error("系统异常:请联系系统管理员");
//        }

//        if (e instanceof JedisConnectionException) {
//            //redis连接异常
//            return new Result(ResultStatusCode.REDIS_CONNECT_ERROR);
//        } else if (e instanceof JedisException) {
//            //redis异常
//            return new Result(ResultStatusCode.REDIS_ERROR);
//        }
        return HttpResult.error(ResultStatusCode.SYSTEM_ERR.getCode(),"系统异常:请联系系统管理员");
    }


}
